package com.zbw.weightlibrary.Connector;

import android.util.Log;

import com.zbw.weightlibrary.Util.ConversionUtil;
import com.zbw.weightlibrary.Util.ThreadPoolManager;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * Created by Administrator on 2018-12-11.
 */

public abstract class BaseControlImplLinLuo implements IBleControl {
    private final DecimalFormat decimalFormat = new DecimalFormat("0.000");
    //添加公共参数、功能等
    private final IinfoCallback mCallback;
    protected boolean ReadWeight;//是否读取重量
    protected ArrayList<byte[]> mRecvData;
    protected int ValueSize;

    public BaseControlImplLinLuo(IinfoCallback callback) {
        mCallback = callback;
    }

    protected void ReadWeight(final InputStream inputStream) {
        ReadWeight = true;
        mRecvData = new ArrayList<>();
        ValueSize = 0;
        ThreadPoolManager.getInstance().executeTask(new Runnable() {
            @Override
            public void run() {
                try {
                    byte[] data = new byte[128];
                    int size;
                    while (inputStream != null && ReadWeight) {
                        if (inputStream.available() > 0) {
                            size = inputStream.read(data);
                            if (size > 0) {
                                ByteBuffer bb = ByteBuffer.allocate(size);
                                bb.put(data, 0, size);
                                postOnReceived(bb.array());
                            } else {
                                break;
                            }
                        } else {
                            Thread.sleep(100);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    mCallback.onGetWeight("获取重量失败！" + e.getMessage(),false);
                }
            }
        });
    }

    protected void postOnReceived(byte[] data) {
        synchronized (mRecvData) {
            mRecvData.add(data);
            while (countByteArrayList(mRecvData) > 1024)
                mRecvData.remove(0);

            byte[] bytes = null;
            synchronized (mRecvData) {
                for (byte[] d : mRecvData) {
                    bytes = d;
                }
            }
            if (bytes != null) {
                CutOutString(bytes);
            }
        }
    }

    /**
     * @param value 接收到的byte数组
     * 麟罗电子秤解析
     */
    protected void CutOutString(byte[] value) {
        //第一步,byte数组转16进制字符串
        String hxStr = ConversionUtil.byte2Hex(value).trim();
        //第二步,用split()方法进行切割，得到对应的数组长度
        String[] data = hxStr.split(" ");
        //第三步，麟罗两种数据格式长度分别为18和25.过滤掉其他长度数据
        if (data.length == 18) {
            type18(data);
        } else if (data.length == 25) {
            type25(data);
        } else {
            Log.i("过滤掉无用数据",hxStr);
        }
    }

    /**
     * 长度为18类型解析
     */
    private void type18(String[] data){
        if(mCallback!=null) {
            //校验通过，开始解析数据详情
            //稳定 53 54 开头
            boolean sta = "53".equals(data[0])&&"54".equals(data[1]);
            String sign = "2d".equals(data[6])?"-":"";
            String netWeight = getStringByIndex(7,14,data);
            netWeight = String.format("%s%s", sign, ConversionUtil.hexStr2Str(netWeight).trim());
            netWeight = dataConversion(netWeight);
            mCallback.onGetWeight(netWeight, sta);
        }
    }

    /**
     * 长度为25类型解析
     * 1.固定开头 01 02，固定结尾03 04
     */
    private void type25(String[] data){
        //通过数据头，数据尾验证
        if("01".equals(data[0])&& "02".equals(data[1])&& "03".equals(data[23])&& "04".equals(data[24])){
            //进行校验BBC算法
            Boolean checkValue = checkBBC(data);
            if(checkValue){
                //校验通过，开始解析数据详情
                String sta1 = data[2];
                String sign = data[3];
                String netWeight = getStringByIndex(4,11,data);
                String tareWeight = getStringByIndex(13,20,data);
                parsing25(sta1,sign,netWeight,tareWeight);
            }else{
                Log.i("type25_BBC校验", "校验不通过");
            }
        }else{
            Log.i("type25", Arrays.toString(data));
        }
    }

    /**
     * 解析25位长度的数据
     * @param sta1 是否稳定，46重量溢出或者开机未归零。53重量稳定。55重量不稳定
     * @param sign 符号位 2d重量位负数。2b重量为正或者为0
     * @param netWeight 净重
     * @param tareWeight 皮重
     */
    private void parsing25(String sta1,String sign,String netWeight,String tareWeight){
        if(mCallback!=null) {
            String netWeightStr;
            if("2d".equals(sign)){
                netWeightStr = String.format("-%s", ConversionUtil.hexStr2Str(netWeight).trim());
            }else{
                netWeightStr = ConversionUtil.hexStr2Str(netWeight);
            }
            netWeightStr = dataConversion(netWeightStr);
            String tareWeightStr = ConversionUtil.hexStr2Str(tareWeight);
            tareWeightStr = dataConversion(tareWeightStr);
            mCallback.onGetWeight(netWeightStr, "53".equals(sta1));
        }
    }

    /**
     * 输出格式转换
     */
    private String dataConversion(String data){
        return decimalFormat.format(Double.valueOf(data));
    }

    /**
     * 拼接对应范围内的数组
     * @param start 开始位置
     * @param end 结束位置
     * @param data 目标数组
     * @return 指定范围拼接的字符串
     */
    private String getStringByIndex(int start,int end,String[] data){
        StringBuilder checkStr = new StringBuilder();
        //检验内容是除去数据头尾和校验字符
        for (int i=start;i<end;i++){
            checkStr.append(data[i]);
        }
        return checkStr.toString();
    }

    /**
     * 校验数据是否正确
     * @param data 校验数据
     * @return 是否校验成功
     */
    private Boolean checkBBC(String[] data){
        //检验内容是除去数据头尾和校验字符
        String checkValue = getStringByIndex(2,22,data);
        //需要的校验数据转byte数组
        byte[] bytes = ConversionUtil.hexStringToByteArray(checkValue);
        String value = ConversionUtil.getBCC(bytes).toLowerCase();
        return value.equals(data[22]);
    }

    private int countByteArrayList(ArrayList<byte[]> data) {
        int size = 0;
        for (byte[] d : data)
            size += d.length;
        return size;
    }

    /**
     * 发送指令
     */
    protected void sendCode(OutputStream os, String code) {
        if (os == null || code.isEmpty()) return;
        try {
            byte[] bytes = ConversionUtil.hexStringToByteArray(code);
            os.write(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成预制去皮代码
     * @param weight 去皮重量
     * @return 对应代码
     */
    protected String getPrefabTareCode(int weight){
        StringBuilder strWeight = new StringBuilder(weight+"");
        while (strWeight.length()<6){
            strWeight.insert(0, "0");
        }
        String hxStr = "54 "+ ConversionUtil.str2HexStr(strWeight.toString());
        byte[] bytes = ConversionUtil.hexStringToByteArray(hxStr);
        String check = ConversionUtil.getBCC(bytes);
        hxStr = hxStr + " " +check;
        return hxStr;
    }

}
